package com.bjb.vr.remote.controller;



import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bjb.vr.common.ao.ClientLoginAo;
import com.bjb.vr.common.ao.ClientRequestAo;
import com.bjb.vr.common.constant.*;
import com.bjb.vr.common.dto.ResDevice;
import com.bjb.vr.common.dto.ResGroup;
import com.bjb.vr.common.result.BaseErrorCode;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.service.*;
import com.bjb.vr.common.utils.*;
import com.bjb.vr.common.vo.*;
import com.bjb.vr.remote.properties.ServerInfoProperties;
import com.power.common.util.UUIDUtil;
import io.jsonwebtoken.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/remote/v1")
@Slf4j
public class ClientApiController {

    private static final String TOKEN_MAP_KEY = "token";
    private static final String REFRESH_TOKEN_MAP_KEY = "refreshTokenId";
    private static final String UDID_MAP_KEY = "udid";

    @Autowired
    ResDictionaryService resDictionaryService;

    @Autowired
    ResContentService resContentService;

    @Autowired
    OptCusLogoService optCusLogoService;

    @Autowired
    ResBundleService resBundleService;

    @Autowired
    ResDeviceService resDeviceService;

    @Autowired
    SysUpgradeDevLogService sysUpgradeDevLogService;

    @Resource
    private ServerInfoProperties serverInfoProperties;

    @Autowired
    RedisUtil redisUtil;
    /**
     * 头盔登录接口
     * @param clientLoginAo
     * @return
     */
    @RequestMapping(value = "/clientLogin", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<ClientLoginVo> clientLogin(@RequestBody ClientLoginAo clientLoginAo) {
        log.info("request clientLogin param " + clientLoginAo.toString());
        Assert.notNull(clientLoginAo.getUdid(),"设备唯一标识符不能为空");
        // 放行SQL拦截,允许通过
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        BaseResult<ClientLoginVo>  deviceBaseResult =  resDeviceService.getResDeviceLoginVoByUdid(clientLoginAo.getUdid());

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);

        if(!deviceBaseResult.isSuccess()){
            log.error("设备登录失败,设备标识 {} 不在系统中",clientLoginAo.getUdid());
            return CommonResult.Fail(BaseErrorCode.NOTFOUND.getCode(),"设备不在系统中");
        }

        ThreadLocalUtil.set(ThreadLocalConstant.DEV_INFO, deviceBaseResult.getData());

        String token = JwtTokenUtil.createDevJWT(clientLoginAo.getUdid(),deviceBaseResult.getData().getTenantId());
        String refreshToken = UUIDUtil.getUuid32();

        //数据放入redis
        redisUtil.hset(TokenConstants.LOGIN_TOKEN_KEY + refreshToken, TOKEN_MAP_KEY, token);
        redisUtil.hset(TokenConstants.LOGIN_TOKEN_KEY + refreshToken, UDID_MAP_KEY, clientLoginAo.getUdid());
        redisUtil.expire(TokenConstants.LOGIN_TOKEN_KEY + refreshToken, TokenConstants.EXPIRATION*60);

        ClientLoginVo clientLoginVo = deviceBaseResult.getData();
        clientLoginVo.setToken(token);
        clientLoginVo.setRefreshToken(refreshToken);
        if(clientLoginVo.getValidBegin()!=null
                && clientLoginVo.getValidEnd()!=null
                && clientLoginVo.getValidEnd().compareTo(clientLoginVo.getValidBegin()) >=0) {
            int validDays = DateTimeUtil.betweenDays(clientLoginVo.getValidBegin(),clientLoginVo.getValidEnd());
            clientLoginVo.setValidDays(validDays);
        }
        if(isNeedUpdateDevApk(clientLoginVo.getDbApkNeedUpdState(),clientLoginAo.getVersionName(),clientLoginVo.getUpdateVersionName())){
            clientLoginVo.setApkNeedUpdState(RemoteContants.APK_UPDATE_STATE_NEED);
            if(serverInfoProperties.getDeployMode().equals(RemoteContants.DEPLOY_MODE_LOCAL)) {
                clientLoginVo.setDownloadUrl(serverInfoProperties.getUpgradeApkUrl() + clientLoginVo.getDownloadUrl());
            }else{
                AliyunOssUtil ossUtil = new AliyunOssUtil.Builder().build(AliOssConstants.ENDPOINT, AliOssConstants.ACCESS_KEY_ID, AliOssConstants.ACCESS_KEY_SECRET);
                String downLoadUrl = ossUtil.getFileUrl(clientLoginVo.getDownloadUrl());
                clientLoginVo.setDownloadUrl(downLoadUrl);
            }
            //需要升级,直接返回
            return CommonResult.Ok().setResult(clientLoginVo);
        }else{
            clientLoginVo.setApkNeedUpdState(RemoteContants.APK_UPDATE_STATE_NO);
            //如果需要升级，版本号相同认为升级完成
            if(clientLoginVo.getDbApkNeedUpdState() == RemoteContants.APK_UPDATE_STATE_NEED){
                ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

                updateApkUpdState(clientLoginAo.getUdid(),clientLoginAo.getVersionName(),clientLoginVo.getUpdateVersionName());

                ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
            }
        }

        return CommonResult.Ok().setResult(clientLoginVo);
    }

    /**
     * 返回头盔，判断是否需要更新apk
     * @param versionName 设备请求的apkversionName
     * @param updateVersionName
     * @return
     */
    private boolean isNeedUpdateDevApk(int dbApkNeedUpdState, String versionName,String updateVersionName){
        if(dbApkNeedUpdState!= RemoteContants.APK_UPDATE_STATE_NEED){
            return false;
        }

        if(StringUtils.isEmpty(updateVersionName)) {
            return false;
        }
        if(StringUtils.isEmpty(versionName)) {
            return false;
        }
        if(!versionName.equals(updateVersionName)){
            return true;
        }
        return false;
    }


    /**
     * 更新头盔apk升级状态
     * @param udid
     * @param versionName
     * @param updateVersionName
     */
    private void updateApkUpdState(String udid,String versionName,String updateVersionName){

        if(StringUtils.isEmpty(versionName) || StringUtils.isEmpty(updateVersionName)){
            return;
        }
        if(!versionName.equals(updateVersionName)){
            return;
        }

        UpdateWrapper<ResDevice> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("apk_need_upd_state",RemoteContants.APK_UPDATE_STATE_FINISH);
        updateWrapper.eq("udid",udid);
        //更新设备是否需要更新为更新完成状态
        resDeviceService.update(updateWrapper);
        //更新设备更新记录表最后一条记录为成功状态
        sysUpgradeDevLogService.updateSysUpdateState(udid,RemoteContants.APK_UPGRADE_STATUS_SUCCESS,"");

    }

    /**
     * 刷新token
     *
     * @param refreshTokenId
     * @return
     */
    @GetMapping("/refreshToken")
    public CommonResult refreshToken(@Valid @RequestParam String refreshTokenId) {
        String oldToken = (String) redisUtil.hget(TokenConstants.LOGIN_TOKEN_KEY + refreshTokenId,TOKEN_MAP_KEY);
        String udid = (String) JwtTokenUtil.parseJWT(oldToken).get(UDID_MAP_KEY);
        String tenantId = (String) JwtTokenUtil.parseJWT(oldToken).get(TokenConstants.TENANT_ID);
        if (StringUtils.isBlank(udid)) {
            return CommonResult.Fail(BaseErrorCode.ERROR_REFRESHMENT);
        }

        //生成新的token
        String newToken = JwtTokenUtil.createDevJWT(udid,tenantId);
        redisUtil.hset(TokenConstants.LOGIN_TOKEN_KEY + refreshTokenId, TOKEN_MAP_KEY, newToken);
        redisUtil.hset(TokenConstants.LOGIN_TOKEN_KEY + refreshTokenId, UDID_MAP_KEY, udid);
        redisUtil.expire(TokenConstants.LOGIN_TOKEN_KEY + refreshTokenId,TokenConstants.EXPIRATION*60);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put(TOKEN_MAP_KEY, newToken);
        jsonObject.put(REFRESH_TOKEN_MAP_KEY, refreshTokenId);
        return CommonResult.Ok().setResult(jsonObject);
    }

    /**
     * 获取设备更新资源列表
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getUpdateResContentList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ClientResBundleVo>> getUpdateResContentList(@RequestBody ClientRequestAo clientRequestAo) {
        log.info("request getUpdateResContentList " + " param " + clientRequestAo.getUdid());

        BaseResult<List<ClientResBundleVo>> result = new CommonResult<List<ClientResBundleVo>>(false);
        result = resBundleService.getUpdateResBundleAndContentByUdid(clientRequestAo.getUdid());
        return result;
    }

    /**
     * 获取课程资源列表接口
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getResCourseList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResClientCourseVo>> getResCourseList(@RequestBody ClientRequestAo clientRequestAo) {
        log.info("request getResCourseList " + " param " + clientRequestAo.getUdid());

        BaseResult<List<ResClientCourseVo>> result = new CommonResult<List<ResClientCourseVo>>(false);
        result = resContentService.getClientResCourseList(clientRequestAo.getUdid());
        return result;
    }


    /**
     * 获取课程资源列表接口
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getDevLogo", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<OptCusLogoVo> getDevLogo(@RequestBody ClientRequestAo clientRequestAo) {
        log.info("request getResCourseList " + " param " + clientRequestAo.getUdid());
        OptCusLogoVo optCusLogoVo = optCusLogoService.getDevLogoPath(clientRequestAo.getUdid());
        return CommonResult.Ok().setResult(optCusLogoVo);
    }


    /**
     * 获取推荐课程资源列表接口
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getRecommendResCourseList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResClientCourseVo>> getRecommendResCourseList(@RequestBody ClientRequestAo clientRequestAo) {

        log.info("request getRecommendResCourseList " + " param " + clientRequestAo.getUdid());

        BaseResult<List<ResClientCourseVo>> result = new CommonResult<ResGroup>(false);
        result = resContentService.getClientResCourseList(clientRequestAo.getUdid());
        return result;
    }

    /**
     * 获取关联学段列表
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getPeriodList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResDictionaryVo>> getPeriodList(@RequestBody ClientRequestAo clientRequestAo) {

        List<ResDictionaryVo> dictionaryVoList = new ArrayList<>();
        dictionaryVoList = resDictionaryService.getResDictionaryList(ResDicType.PERIOD.getType());

        return CommonResult.Ok().setResult(dictionaryVoList);
    }

    /**
     * 获取年级列表
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getLevelList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResDictionaryVo>> getLevelList(@RequestBody ClientRequestAo clientRequestAo) {

        List<ResDictionaryVo> dictionaryVoList = new ArrayList<>();
        dictionaryVoList = resDictionaryService.getResDictionaryList(ResDicType.LEVEL.getType());

        return CommonResult.Ok().setResult(dictionaryVoList);
    }

    /**
     * 获取出版社列表
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getPressList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResDictionaryVo>> getPressList(@RequestBody ClientRequestAo clientRequestAo) {

        List<ResDictionaryVo> dictionaryVoList = new ArrayList<>();
        dictionaryVoList = resDictionaryService.getResDictionaryList(ResDicType.PRESS.getType());

        return CommonResult.Ok().setResult(dictionaryVoList);
    }


    /**
     * 获取学科列表
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getSubjectList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResDictionaryVo>> getSubjectList(@RequestBody ClientRequestAo clientRequestAo) {

        List<ResDictionaryVo> dictionaryVoList = new ArrayList<>();
        dictionaryVoList = resDictionaryService.getResDictionaryList(ResDicType.SUBJECT.getType(),clientRequestAo);

        return CommonResult.Ok().setResult(dictionaryVoList);
    }

    /**
     * 获取资源类型列表
     * @param clientRequestAo
     * @return
     */
    @RequestMapping(value = "/getTypeList", method = {RequestMethod.GET,RequestMethod.POST})
    public BaseResult<List<ResDictionaryVo>> getTypeList(@RequestBody ClientRequestAo clientRequestAo) {

        List<ResDictionaryVo> dictionaryVoList = new ArrayList<>();
        dictionaryVoList = resDictionaryService.getResDictionaryList(ResDicType.RESOURCE_TYPE.getType());

        return CommonResult.Ok().setResult(dictionaryVoList);
    }
}
